/*
Copyright (C) 2022-2024 Inspur Corp.

SPDX-License-Identifier: Apache-2.0
*/
package controller

import (
	"github.com/emicklei/go-restful"
	"github.com/go-redis/redis"
	"icep/auth"
	"icep/bean/model"
	"icep/bean/param"
	view2 "icep/bean/view"
	"icep/common/cryptoprovider"
	"icep/common/http"
	"icep/common/jwt"
	"icep/plugins/sessionmgr"
	"strings"
	"time"
)

func (ic *IcepController) Login(req *restful.Request, resp *restful.Response) {
	var loginParam param.LoginParam
	if err := req.ReadEntity(&loginParam); err != nil {
		log.Errorf("login read entity error: %v", err)
		http.Failed(resp, "请求参数不合法！")
		return
	}

	if loginParam.Account == "" || loginParam.Password == "" {
		http.Failed(resp, "请求参数不合法！")
		return
	}

	locked, msg := ic.lockTool.IsAccountLocked(loginParam.Account)
	if locked {
		http.Failed(resp, msg)
		return
	}

	userDetail, err := ic.IcepService.GetUserByAccount(loginParam.Account)
	if err != nil {
		log.Errorf("login get user error: %v", err)
		http.Failed(resp, "登录失败！")
		return
	}
	if userDetail == nil {
		log.Warning("user not exist")
		http.Failed(resp, "用户或密码错误！")
		ic.lockTool.HandleLoginFailed(loginParam.Account)
		return
	}

	// 获取密码
	//password := sha256.Sha256(loginParam.Password + config2.Get("icep.salt", constant.DefaultSalt))
	password := loginParam.Password
	if !cryptoprovider.Get().Check(userDetail.Password, password) {
		log.Warning("password wrong")
		http.Failed(resp, "用户或密码错误！")
		ic.lockTool.HandleLoginFailed(loginParam.Account)
		return
	}

	token := jwt.GenerateToken(userDetail.Id, userDetail.UserType, userDetail.TenantId, userDetail.Phone, userDetail.Mail)
	if token == "" {
		log.Error("failed to generate token")
		http.Failed(resp, "令牌生成失败！")
		return
	}
	sessionmgr.Get().Add(userDetail.Id, token, req.Request)
	loginView := view2.LoginView{Token: token}
	resp.Header().Add("Authorization", token)
	http.OkWithData(resp, "登录成功", loginView)
	ic.lockTool.HandleLoginSuccess(loginParam.Account)

}

func (ic *IcepController) Logout(req *restful.Request, resp *restful.Response) {
	userId := auth.GetCurrentUserId(req)
	sessionmgr.Get().Remove(userId)
	http.Ok(resp, "登出成功")
}

func handleLoginResult(errorCount int64, password string, userDetail *model.UserDetail, loginParam param.LoginParam, client *redis.Client, resp *restful.Response) {

	if errorCount >= 5 {
		// 连续错误登录次数超过 5 次，将账号状态设为锁定，设置过期时间
		client.Set(loginParam.Account+"_account_locked", 1, time.Hour)
		client.Exists(loginParam.Account + "_account_locked")
		http.Failed(resp, "密码连续输入错误五次,请一小时后重试！")
		return

	} else if password != userDetail.Password {
		// 密码错误，增加连续错误登录次数, 更新 Redis 中该账号的信息
		//errorCount++
		//client.HSet(loginParam.Account+"_login_info", "error_count", strconv.Itoa(errorCount))
		log.Warning("password wrong")
		http.Failed(resp, "用户或密码错误！")
		return
	}
	// 生成令牌并返回给客户端
	token := jwt.GenerateToken(userDetail.Id, userDetail.UserType, userDetail.TenantId, userDetail.Phone, userDetail.Mail)
	if token == "" {
		log.Error("failed to generate token")
		http.Failed(resp, "令牌生成失败！")
		return
	}
	loginView := view2.LoginView{Token: token}
	resp.Header().Add("Authorization", token)
	http.OkWithData(resp, "登录成功", loginView)
	client.Del(loginParam.Account + "_account_retry")
	return
}

func GetTimeValues(remainingTime time.Duration) (string, string) {
	remainingTimeString := remainingTime.String()
	mIndex := strings.Index(remainingTimeString, "m")
	var minutes string
	if mIndex > 0 {
		minutes = remainingTimeString[:mIndex]
	}
	m1 := mIndex + 1
	sIndex := strings.Index(remainingTimeString, "s")
	seconds := remainingTimeString[m1:sIndex]
	return minutes, seconds
}
